package com.school.util;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.security.SecureRandom;
import java.util.regex.Pattern;

/**
 * 密码工具类
 * 
 * @author School Development Team
 * @version 1.0.0
 * @since 2024
 */
public class PasswordUtil {

    private static final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    
    // 密码强度正则表达式
    private static final String WEAK_PASSWORD_PATTERN = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$";
    private static final String MEDIUM_PASSWORD_PATTERN = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
    private static final String STRONG_PASSWORD_PATTERN = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{12,}$";
    
    private static final Pattern weakPattern = Pattern.compile(WEAK_PASSWORD_PATTERN);
    private static final Pattern mediumPattern = Pattern.compile(MEDIUM_PASSWORD_PATTERN);
    private static final Pattern strongPattern = Pattern.compile(STRONG_PASSWORD_PATTERN);

    /**
     * 加密密码
     * 
     * @param rawPassword 原始密码
     * @return 加密后的密码
     */
    public static String encodePassword(String rawPassword) {
        if (rawPassword == null || rawPassword.trim().isEmpty()) {
            throw new IllegalArgumentException("密码不能为空");
        }
        return passwordEncoder.encode(rawPassword);
    }

    /**
     * 验证密码
     * 
     * @param rawPassword 原始密码
     * @param encodedPassword 加密后的密码
     * @return 是否匹配
     */
    public static boolean matches(String rawPassword, String encodedPassword) {
        if (rawPassword == null || encodedPassword == null) {
            return false;
        }
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    /**
     * 检查密码强度
     * 
     * @param password 密码
     * @return 密码强度等级
     */
    public static PasswordStrength checkPasswordStrength(String password) {
        if (password == null || password.length() < 6) {
            return PasswordStrength.VERY_WEAK;
        }
        
        if (strongPattern.matcher(password).matches()) {
            return PasswordStrength.STRONG;
        } else if (mediumPattern.matcher(password).matches()) {
            return PasswordStrength.MEDIUM;
        } else if (weakPattern.matcher(password).matches()) {
            return PasswordStrength.WEAK;
        } else {
            return PasswordStrength.VERY_WEAK;
        }
    }

    /**
     * 验证密码格式
     * 
     * @param password 密码
     * @return 验证结果
     */
    public static PasswordValidationResult validatePassword(String password) {
        PasswordValidationResult result = new PasswordValidationResult();
        
        if (password == null || password.trim().isEmpty()) {
            result.setValid(false);
            result.setMessage("密码不能为空");
            return result;
        }
        
        if (password.length() < 6) {
            result.setValid(false);
            result.setMessage("密码长度不能少于6位");
            return result;
        }
        
        if (password.length() > 50) {
            result.setValid(false);
            result.setMessage("密码长度不能超过50位");
            return result;
        }
        
        // 检查是否包含空格
        if (password.contains(" ")) {
            result.setValid(false);
            result.setMessage("密码不能包含空格");
            return result;
        }
        
        // 检查密码强度
        PasswordStrength strength = checkPasswordStrength(password);
        result.setValid(true);
        result.setStrength(strength);
        
        switch (strength) {
            case VERY_WEAK:
                result.setMessage("密码强度很弱，建议包含大小写字母和数字");
                break;
            case WEAK:
                result.setMessage("密码强度较弱，建议添加特殊字符");
                break;
            case MEDIUM:
                result.setMessage("密码强度中等");
                break;
            case STRONG:
                result.setMessage("密码强度很强");
                break;
        }
        
        return result;
    }

    /**
     * 生成随机密码
     * 
     * @param length 密码长度
     * @return 随机密码
     */
    public static String generateRandomPassword(int length) {
        if (length < 8) {
            length = 8;
        }
        
        String upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String lowerCase = "abcdefghijklmnopqrstuvwxyz";
        String digits = "0123456789";
        String specialChars = "@$!%*?&";
        String allChars = upperCase + lowerCase + digits + specialChars;
        
        SecureRandom random = new SecureRandom();
        StringBuilder password = new StringBuilder();
        
        // 确保至少包含一个大写字母、小写字母、数字和特殊字符
        password.append(upperCase.charAt(random.nextInt(upperCase.length())));
        password.append(lowerCase.charAt(random.nextInt(lowerCase.length())));
        password.append(digits.charAt(random.nextInt(digits.length())));
        password.append(specialChars.charAt(random.nextInt(specialChars.length())));
        
        // 填充剩余长度
        for (int i = 4; i < length; i++) {
            password.append(allChars.charAt(random.nextInt(allChars.length())));
        }
        
        // 打乱字符顺序
        char[] passwordArray = password.toString().toCharArray();
        for (int i = passwordArray.length - 1; i > 0; i--) {
            int j = random.nextInt(i + 1);
            char temp = passwordArray[i];
            passwordArray[i] = passwordArray[j];
            passwordArray[j] = temp;
        }
        
        return new String(passwordArray);
    }

    /**
     * 密码强度枚举
     */
    public enum PasswordStrength {
        VERY_WEAK("很弱"),
        WEAK("较弱"),
        MEDIUM("中等"),
        STRONG("很强");
        
        private final String description;
        
        PasswordStrength(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }

    /**
     * 密码验证结果
     */
    public static class PasswordValidationResult {
        private boolean valid;
        private String message;
        private PasswordStrength strength;
        
        public PasswordValidationResult() {
        }
        
        public PasswordValidationResult(boolean valid, String message) {
            this.valid = valid;
            this.message = message;
        }
        
        public boolean isValid() {
            return valid;
        }
        
        public void setValid(boolean valid) {
            this.valid = valid;
        }
        
        public String getMessage() {
            return message;
        }
        
        public void setMessage(String message) {
            this.message = message;
        }
        
        public PasswordStrength getStrength() {
            return strength;
        }
        
        public void setStrength(PasswordStrength strength) {
            this.strength = strength;
        }
        
        @Override
        public String toString() {
            return "PasswordValidationResult{" +
                    "valid=" + valid +
                    ", message='" + message + '\'' +
                    ", strength=" + strength +
                    '}';
        }
    }
}